home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
netconf
/
daemons.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-01
|
14KB
|
565 lines
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <signal.h>
#include "netconf.h"
#include "internal.h"
#include "../paths.h"
#include "../xconf/xconf.h"
#include "netconf.m"
static NETCONF_HELP_FILE help_inetd("inetd");
static CONFIG_FILE f_inetd (ETC_INETD_CONF,help_inetd,CONFIGF_PROBED);
static NETCONF_HELP_FILE help_amd("amd");
static CONFIG_FILE f_conf_amd (ETC_CONF_AMD_MAP,help_amd,CONFIGF_PROBED);
static NETCONF_HELP_FILE help_gated("gated");
static CONFIG_FILE f_gated (ETC_GATED_CONF,help_gated,CONFIGF_PROBED);
static NETCONF_HELP_FILE help_ssh ("ssh");
static CONFIG_FILE f_ssh_host_key (ETC_SSH_HOST_KEY,help_ssh,CONFIGF_PROBED);
extern CONFIG_FILE f_exports;
/* #Specification: daemon / classes
The class DAEMON is the base class. Each daemon (portmap, inetd, ...)
may have its own class where it generally overide the method
startif and stop.
*/
#
class DAEMON_INETD: public DAEMON{
/*~PROTOBEG~ DAEMON_INETD */
public:
int restart (void);
int startif (void);
/*~PROTOEND~ DAEMON_INETD */
};
/*
Tell inetd to reread its configuration file
*/
PUBLIC int DAEMON_INETD::restart()
{
int ret = -1;
PROC *prc = process_find(path);
if (prc != NULL){
if (file_date (VAR_RUN_INETD_SIGHUP) < f_inetd.getdate()){
ret = signal (SIGHUP,"Signaling",VAR_RUN_INETD_SIGHUP);
}
}
return ret;
}
PUBLIC int DAEMON_INETD::startif()
{
/* #Specification: inetd / strategy
inetd depend on /etc/inetd.conf. If the file is empty
or do not exist, then inetd is not need. It will be
killed, or not started.
If inetd.conf is not empty, it will be started. If it is
already running and exports is younger than the process,
the signal SIGHUP is sent so inetd will reread inetd.conf.
*/
return startif_file(ETC_INETD_CONF);
}
class DAEMON_PORTMAP: public DAEMON{
/*~PROTOBEG~ DAEMON_PORTMAP */
/*~PROTOEND~ DAEMON_PORTMAP */
};
class DAEMON_AMD: public DAEMON{
/*~PROTOBEG~ DAEMON_AMD */
public:
int restart (void);
int startif (void);
int stop (void);
/*~PROTOEND~ DAEMON_AMD */
};
/*
Stop the automounter
*/
PUBLIC int DAEMON_AMD::stop ()
{
return kill(SIGINT);
}
/*
Tell the automounter to reread its configuration file.
*/
PUBLIC int DAEMON_AMD::restart ()
{
/* #Specification: amd / restarting
When the map (/etc/conf.amd.map) is changed, amd is simply
restarted. It is killed with SIGINT and restarted. This is
weak as it is unmounting everything. On the other hand
I suspect that amd will be managed only in single user
mode so it does not matter. Some amd guru want to comment.
*/
int ret = stop();
if (ret != -1) ret = start();
return ret;
}
/*
Restart amd if ETC_CONF_AMD_MAP is newer than the process
*/
PUBLIC int DAEMON_AMD::startif ()
{
/* #Specification: amd automounter / strategy
amd depends on /etc/conf.amd.map. If the file is empty
or do not exist, then amd is not need. It will be
killed, or not started.
If /etc/conf.amd.map is not empty, it will be started. If it is
already running and exports is younger than the process,
it will be kill and restart
*/
return startif_file (f_conf_amd);
}
class DAEMON_LPD: public DAEMON{
/*~PROTOBEG~ DAEMON_LPD */
/*~PROTOEND~ DAEMON_LPD */
};
class DAEMON_NFSD: public DAEMON{
/*~PROTOBEG~ DAEMON_NFSD */
public:
int startif (void);
/*~PROTOEND~ DAEMON_NFSD */
};
/*
Restart nfsd if ETC_EXPORTS is newer than the process
*/
PUBLIC int DAEMON_NFSD::startif ()
{
/* #Specification: rpc.nfsd / strategy
rpc.nfsd depends on /etc/exports. If the file is empty
or do not exist, then rpc.nfsd is not need. It will be
killed, or not started.
If exports is not empty, it will be started. If it is
already running and exports is younger than the process,
it will be kill and restart.
I suspect there is a way to update nfsd without killing it.
Someone is aware of this ?
*/
return startif_file(f_exports);
}
class DAEMON_MOUNTD: public DAEMON{
/*~PROTOBEG~ DAEMON_MOUNTD */
public:
int startif (void);
/*~PROTOEND~ DAEMON_MOUNTD */
};
/*
Restart mountd if ETC_EXPORTS is newer than the process
*/
PUBLIC int DAEMON_MOUNTD::startif ()
{
/* #Specification: rpc.mountd / strategy
rpc.mountd depends on /etc/exports. If the file is empty
or do not exist, then rpc.mountd is not need. It will be
killed, or not started.
If exports is not empty, it will be started. If it is
already running and exports is younger than the process,
it will be kill and restart
*/
return startif_file(f_exports);
}
class DAEMON_NAMED: public DAEMON{
/*~PROTOBEG~ DAEMON_NAMED */
public:
int startif (void);
/*~PROTOEND~ DAEMON_NAMED */
};
/*
Restart named if ETC_NAMED_BOOT is newer than the process
*/
PUBLIC int DAEMON_NAMED::startif ()
{
/* #Specification: named / strategy
named depends on /etc/named.boot and many others configuration
files. If the file is empty or do not exist, then named
is not need. It will be killed, or not started.
If named.boot is not empty, it will be started. If it is
already running and named.boot is younger than the process,
it will be killed and restarted.
This is not completed yet. Normally, we should check for all
file processed by named to check if any one is younger. This
is not done now, as another project (the named editor) will
take care of named.
*/
extern CONFIG_FILE f_boot;
return startif_file(f_boot);
}
class DAEMON_GATED: public DAEMON{
/*~PROTOBEG~ DAEMON_GATED */
public:
int restart (void);
int start (void);
int startif (void);
int stop (void);
/*~PROTOEND~ DAEMON_GATED */
};
/*
Restart gated if ETC_GATED_CONF is newer than the process
*/
PUBLIC int DAEMON_GATED::startif ()
{
/* #Specification: gated / strategy
gated depends on /etc/gated.conf.
If the file is empty or do not exist, then gated
is not need. It will be killed, or not started.
If gated.conf is not empty, it will be started. If it is
already running and gated.conf is younger than the process,
it will be kill and restart.
*/
return startif_file(f_gated);
}
/*
Tell gated to reread its configuration file
*/
PUBLIC int DAEMON_GATED::restart()
{
char buf[2000];
sprintf (buf,"%s restart",path);
return system (buf);
}
/*
Tell gated to stop
*/
PUBLIC int DAEMON_GATED::stop()
{
int ret = 0;
if (process_find(path)!=NULL){
char buf[2000];
sprintf (buf,"%s stop",path);
ret = system (buf);
}
return ret;
}
/*
Tell gated to start
*/
PUBLIC int DAEMON_GATED::start()
{
char buf[2000];
sprintf (buf,"%s start",path);
return system (buf);
}
class DAEMON_SENDMAIL: public DAEMON{
/*~PROTOBEG~ DAEMON_SENDMAIL */
public:
int startif (void);
/*~PROTOEND~ DAEMON_SENDMAIL */
};
/*
Restart sendmail if ETC_SENDMAIL_CF is newer than the process
*/
PUBLIC int DAEMON_SENDMAIL::startif ()
{
/* #Specification: sendmail / strategy
sendmail depends on /etc/sendmail.cf.
If the file is empty or do not exist, then sendmail
is not need. It will be killed, or not started.
If sendmail.cf is not empty, it will be started. If it is
already running and sendmail.cf is younger than the process,
it will be kill and restart.
*/
extern CONFIG_FILE f_sendmail;
return startif_file(f_sendmail);
}
class DAEMON_ROUTED: public DAEMON{
/*~PROTOBEG~ DAEMON_ROUTED */
private:
void setcmdline (ROUTED&rt, char *cmdline);
public:
int start (void);
int startif (void);
/*~PROTOEND~ DAEMON_ROUTED */
};
PRIVATE void DAEMON_ROUTED::setcmdline(ROUTED &rt, char *cmdline)
{
char buf[20];
rt.setoptions (buf);
sprintf (cmdline,"%s %s %s",path,args,buf);
}
extern NETCONF_HELP_FILE help_routed;
static CONFIG_FILE f_run_routed (VAR_RUN_ROUTED_OPTIONS
,help_routed,CONFIGF_MANAGED|CONFIGF_OPTIONNAL);
PUBLIC int DAEMON_ROUTED::start()
{
ROUTED rt;
char cmdline[PATH_MAX];
setcmdline (rt,cmdline);
if (!simul_ison()){
FILE *fout = f_run_routed.fopen ("w");
if (fout != NULL){
fputs (cmdline,fout);
fclose (fout);
}
}
return system (cmdline);
}
PUBLIC int DAEMON_ROUTED::startif()
{
int ret = 0;
ROUTED rt;
if (!rt.is_required()){
ret = stop();
if (!simul_ison()) unlink (f_run_routed.getpath());
}else{
PROC *prc = process_find(path);
if (prc == NULL){
ret = start();
}else{
/* #Specification: netconf / routed / /var/run/routed.options
netconf save the command line option of routed in
the file /var/run/routed.options each time it is
started.
When checking the configuration, netconf read back
the command line and compare with the configured
one. If there is any difference, routed will
be restarted.
I am not sure how appropriate it is to
restarted. Maybe there is a clean way to kill routed
so it will remove all routes and put it back when
restart. Not sure here...
*/
char old_cmdline[PATH_MAX];
old_cmdline[0] = '\0';
FILE *fin = f_run_routed.fopen ("r");
if (fin != NULL){
fgets (old_cmdline,sizeof(old_cmdline)-1,fin);
fclose (fin);
}
char cmdline[PATH_MAX];
setcmdline (rt,cmdline);
if (strcmp(cmdline,old_cmdline)!=0) ret = restart();
}
}
return ret;
}
class DAEMON_YPBIND: public DAEMON{
/*~PROTOBEG~ DAEMON_YPBIND */
private:
int set_domain (NIS_CONF&nis);
public:
int start (void);
int startif (void);
/*~PROTOEND~ DAEMON_YPBIND */
};
/*
Set the NIS domain name.
Return -1 if not defined, 0 if left unchanged or 1 if changed
*/
PRIVATE int DAEMON_YPBIND::set_domain(NIS_CONF &nis)
{
int ret = -1;
if (nis.configok()){
ret = 0;
const char *domain = nis.getdomain();
char buf[100];
if (getdomainname(buf,sizeof(buf)-1)==-1
|| strcmp(buf,domain)!=0){
if (!simul_ison()){
setdomainname(domain,strlen(domain)+1);
}
ret = 1;
net_prtlog (MSG_U(X_SETNISDOM,"Set NIS domain to %s\n"),domain);
}
}
return ret;
}
/*
Start ypbind.
*/
PUBLIC int DAEMON_YPBIND::start ()
{
int ret = 0;
NIS_CONF nis;
if (set_domain(nis) != -1){
const char *nisserver = nis.getserver();
if (nisserver != NULL){
char buf[2000];
sprintf (buf,"%s -ypset %s",path,args);
ret = -1;
if (system (buf) == 0){
char ypset_path[PATH_MAX];
strcpy (ypset_path,path);
char *pt = ypset_path + strlen(ypset_path) -1;
while (pt >= ypset_path && *pt != '/') pt--;
if (pt >= ypset_path && *pt == '/'){
*pt = '\0';
sprintf(buf,"%s/ypset %s",ypset_path,nisserver);
}else{
sprintf(buf,"ypset %s",nisserver);
}
ret = system (buf);
}
}else{
ret = DAEMON::start();
}
}
return ret;
}
/*
Restart ypbind if ETC_DEFAULTDOMAIN is newer than the process
*/
PUBLIC int DAEMON_YPBIND::startif ()
{
/* #Specification: ypbind / strategy
ypbind is configured in the file /etc/conf.linuxconf
It provides the nis domain and optionnally the nis server
(If it can't be located by a broadcast).
If the nis domain is defined, then ypbind is started.
Depending if a server is specified or not,
ypbind is started this way:
#
No specified NIS server
ypbind
With a specified NIS server
ypbind -ypset
ypset -h nisserver
#
If the configuration file is newer than the current process,
it is killed and restarted.
*/
int ret = 0;
NIS_CONF nis;
int status = set_domain(nis);
if (status == -1){
ret = stop();
}else if (status == 0){
if (process_find(path)==NULL) ret = start();
}else{
ret = restart();
}
return ret;
}
class DAEMON_KLOGD: public DAEMON{
/*~PROTOBEG~ DAEMON_KLOGD */
/*~PROTOEND~ DAEMON_KLOGD */
};
class DAEMON_SYSLOGD: public DAEMON{
/*~PROTOBEG~ DAEMON_SYSLOGD */
/*~PROTOEND~ DAEMON_SYSLOGD */
};
// Not really a daemon, but a system command
class DAEMON_COMMAND: public DAEMON{
/*~PROTOBEG~ DAEMON_COMMAND */
/*~PROTOEND~ DAEMON_COMMAND */
};
class DAEMON_CROND: public DAEMON{
/*~PROTOBEG~ DAEMON_CROND */
/*~PROTOEND~ DAEMON_CROND */
};
class DAEMON_KERNELD: public DAEMON{
/*~PROTOBEG~ DAEMON_KERNELD */
/*~PROTOEND~ DAEMON_KERNELD */
};
class DAEMON_SSHD: public DAEMON{
/*~PROTOBEG~ DAEMON_SSHD */
public:
int startif (void);
/*~PROTOEND~ DAEMON_SSHD */
};
/*
Restart sshd if ETC_SSH_HOST_KEY is newer than the process
*/
PUBLIC int DAEMON_SSHD::startif ()
{
/* #Specification: sshd / strategy
sshd depends on /etc/ssh_host_key at least.
If the file is empty or do not exist, then sshd
is not need. It will be killed, or not started.
If ssh_host_key is not empty, it will be started. If it is
already running and the file is younger than the process,
it will be kill and restart.
*/
return startif_file(f_ssh_host_key);
}
/*
Create an instance of a sub-class of DAEMON based on its name.
*/
DAEMON *daemon_new (
int managed,
const char *name,
const char *buf,
DAEMON *next)
{
DAEMON *ret = NULL;
#define NEWD(n,c) if(strcmp(name,n)==0){ \
ret = new DAEMON_##c; \
}
NEWD("inetd",INETD)
else NEWD ("chat",COMMAND)
else NEWD ("crond",CROND)
else NEWD ("rpc.portmap",PORTMAP)
else NEWD ("named",NAMED)
else NEWD ("routed",ROUTED)
else NEWD ("ypbind",YPBIND)
else NEWD ("amd",AMD)
else NEWD ("klogd",KLOGD)
else NEWD ("syslogd",SYSLOGD)
else NEWD ("rpc.nfsd",NFSD)
else NEWD ("rpc.mountd",MOUNTD)
else NEWD ("lpd",LPD)
else NEWD ("ifconfig",COMMAND)
else NEWD ("ipx_configure",COMMAND)
else NEWD ("ipx_interface",COMMAND)
else NEWD ("kerneld",KERNELD)
else NEWD ("route",COMMAND)
else NEWD ("clock",COMMAND)
else NEWD ("rarp",COMMAND)
else NEWD ("lilo",COMMAND)
else NEWD ("netdate",COMMAND)
else NEWD ("makemap",COMMAND)
else NEWD ("modprobe",COMMAND)
else NEWD ("depmod",COMMAND)
else NEWD ("pppd",COMMAND)
else NEWD ("fdisk",COMMAND)
else NEWD ("telinit",COMMAND)
else NEWD ("mount",COMMAND)
else NEWD ("nslookup",COMMAND)
else NEWD ("umount",COMMAND)
else NEWD ("gated",GATED)
else NEWD ("sendmail",SENDMAIL)
else NEWD ("sshd",SSHD)
else{
xconf_error (MSG_U(E_UNKNOWNDAEMON
,"Unknown daemon :%s:....\ndon't know how to support it\n")
,name);
}
if (ret != NULL){
ret->init(managed,name,buf,next);
}
return ret;
}